package libra.sentinelRestTemplate.call;

import java.io.IOException;
import java.util.Map;

import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpResponse;

import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSON;

/**
 * Sentinel整合RestTemplate的自定义流控异常处理类
 * 启动的时候会检查 @SentinelRestTemplate 注解对应的限流或降级方法是否存在，如不存在会抛出异常！！！
 * 	限流、降级方法的参数列表、返回值需要与org.springframework.http.client.ClientHttpRequestInterceptor#interceptor()方法保持一致
 * 	其中参数多出了一个BlockException类型参数用于获取Sentinel捕获的异常。
 * @author libra
 */
public class BlockExHandler_RestTemplate {
    /**
     * Sentinel整合RestTemplate自定义限流处理方法
     * 注意：必须是static修饰，参数类型不能出错，参数多出了一个BlockException类型参数用于获取Sentinel捕获的异常
     */
    public static SentinelClientHttpResponse handleException(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
		return new SelfSentinelClientHttpResponse( 
			439, JSON.toJSONString( Map.of("type", "block", "ex", ex.getClass().getCanonicalName()) ) );
    }
    
    /**
     * Sentinel整合RestTemplate自定义降级处理方法
     * 注意：必须是static修饰，参数类型不能出错，参数多出了一个BlockException类型参数用于获取Sentinel捕获的异常
     */
    public static ClientHttpResponse handleFallback(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
		return new SelfSentinelClientHttpResponse( 
			449, JSON.toJSONString( Map.of("type", "fallback", "ex", ex.getClass().getCanonicalName()) ) );
    }

}
// 自定义SentinelClientHttpResponse。否则只能返回json数据，不能自定义status状态码
class SelfSentinelClientHttpResponse extends SentinelClientHttpResponse {
	private int status;
	public SelfSentinelClientHttpResponse(int status, String blockResponse) {
		super(blockResponse);
		this.status = status;
	}
	@Override
	public int getRawStatusCode() throws IOException {
		return status;
	}
}
